package com.vision.util.http.down;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * 通用URL资源下载器
 */
public class URLFileDownloader {
    /**
     * 通过资源的URL下载文件到指定目录
     *
     * @param resURL 资源URL
     * @param dest   资源本地存储目的地
     * @return 下载结果 true 成功 / false 失败
     */
    public static boolean download(String resURL, OutputStream dest) {

        URL url = null;
        HttpURLConnection conn = null;

        if (dest == null) {
            System.err.println("资源本地存储目的地不存在！");
            return false;
        }

        try {
            url = new URL(resURL);
            conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(10000);
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream is = conn.getInputStream();
                copy(is, dest);
            }

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
            if (dest != null) {
                try {
                    dest.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }

    /**
     * 通过资源的URL下载文件到指定目录
     *
     * @param resURL    资源URL
     * @param localPath 资源本地存储目录
     * @param fileName  文件名
     * @return 下载结果 true 成功 / false 失败
     */
    public static boolean download(String resURL, String localPath, String fileName) {

        try {
            return download(resURL, new FileOutputStream(new File(localPath, fileName)));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取资源
     *
     * @param resURL 资源URL
     * @return 下载结果 true 成功 / false 失败
     */
    public static HttpsURLConnection httpsDownload(String resURL) {
        HttpsURLConnection conn = null;
        try {
            URL url = new URL(resURL);
            conn = (HttpsURLConnection) url.openConnection();
            conn.setReadTimeout(10000);

            SSLSocketFactory ssf = getSslSocketFactory();
            conn.setSSLSocketFactory(ssf);
        } catch (Exception e) {
            e.printStackTrace();
            return conn;
        }
        return conn;
    }

    /**
     * 获取资源
     *
     * @param resURL 资源URL
     * @return 下载结果 true 成功 / false 失败
     */
    public static HttpURLConnection httpDownload(String resURL) {
        HttpURLConnection conn = null;
        try {
            URL url = new URL(resURL);
            conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(10000);

            // SSLSocketFactory ssf = getSslSocketFactory();
            // conn.setSSLSocketFactory(ssf);
        } catch (Exception e) {
            e.printStackTrace();
            return conn;
        }
        return conn;
    }

    /**
     * 通过资源的URL下载文件到指定目录
     *
     * @param resURL 资源URL
     * @param dest   资源本地存储目的地
     * @return 下载结果 true 成功 / false 失败
     */
    public static boolean httpsDownload(String resURL, OutputStream dest) {

        URL url = null;
        HttpsURLConnection conn = null;

        if (dest == null) {
            System.err.println("资源本地存储目的地不存在！");
            return false;
        }

        try {
            url = new URL(resURL);
            conn = (HttpsURLConnection) url.openConnection();
            conn.setReadTimeout(10000);

            SSLSocketFactory ssf = getSslSocketFactory();
            conn.setSSLSocketFactory(ssf);

            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream is = conn.getInputStream();
                copy(is, dest);
            }

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
            if (dest != null) {
                try {
                    dest.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }

    private static SSLSocketFactory getSslSocketFactory() throws NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {
        TrustManager[] tm = {new MyX509TrustManager()};
        SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
        sslContext.init(null, tm, new java.security.SecureRandom());
        return sslContext.getSocketFactory();
    }

    /**
     * 通过资源的URL下载文件到指定目录
     *
     * @param resURL    资源URL
     * @param localPath 资源本地存储目录
     * @param fileName  文件名
     * @return 下载结果 true 成功 / false 失败
     */
    public static boolean httpsDownload(String resURL, String localPath, String fileName) {

        try {
            return httpsDownload(resURL, new FileOutputStream(new File(localPath, fileName)));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 流拷贝
     *
     * @param is 输入流
     * @param os 输出流
     * @throws IOException 异常
     */
    private static void copy(InputStream is, OutputStream os) throws IOException {
        byte[] buffer = new byte[4096];
        int n = 0;
        while (-1 != (n = is.read(buffer))) {
            os.write(buffer, 0, n);
        }
    }

    private static class MyX509TrustManager implements X509TrustManager {

        // 检查客户端证书
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        // 检查服务器端证书
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        // 返回受信任的X509证书数组
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }

    public static void main(String[] args) {
        download("http://192.240.120.2/mp43/212324.mp4?st=jUWgfHov0t8-Ln0MHKUQCA&e=1494153545 ","E:\\22","22.mp4");
    }

}
